package net.esj.basic.view;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import javax.annotation.PostConstruct;

import net.esj.basic.core.view.action.SearcherActionAware;
import net.esj.basic.core.view.tools.ActionContext;
import net.esj.basic.core.view.tools.searcher.Searcher;
import net.esj.basic.core.view.tools.searcher.SearcherColumn;
import net.esj.basic.dao.querybuilder.OrderExpression;
import net.esj.basic.dao.querybuilder.QueryBuilder;
import net.esj.basic.dao.querybuilder.SymbolExpression;
import net.esj.basic.exception.MelonException;
import net.esj.basic.exception.MelonRuntimeException;
import net.esj.basic.pojo.AbstractPojo;
import net.esj.basic.pojo.PrimaryKey;
import net.esj.basic.service.DefaultService;
import net.esj.basic.utils.Pagination;
import net.esj.basic.utils.StringUtils;
import net.esj.basic.utils.Validators;
import net.esj.basic.utils.i18n.MessageCode;
import net.esj.basic.utils.view.BaseJsonMessage.MessageLevel;
import net.esj.basic.utils.writer.WriterCode;

/**
 * 对于entity的setter&getter方法必须在子类中实现,且不能继承或重载
 * 
 * @author Administrator
 *
 * @param <P> POJO对象
 * @param <V> VO对象
 */
public abstract class PageAction<P,V> extends BaseAction implements MessageCode,SearcherActionAware{

	/**
	 * 
	 */
	private static final long serialVersionUID = 2017984924475912475L;
	
	protected Pagination pagination;

	protected Class<P> entityClass;
	
	protected Class<V> voClass;

	protected String deletes;

	protected String id;

	//必须在子类被setter、getter
	protected V entity;
	
	protected DefaultService defaultService;
	
	protected boolean ajax = true;

	protected boolean checkbox = false;
	
	@PostConstruct
	public void initConstruct() {
		//entityClass = (Class<P>) generateClass()[0];
		//voClass = (Class<V>) generateClass()[1];
		generateClass();
		if(voClass!=null){
			try {
				entity = voClass.newInstance();
			} catch (Exception e) {
			}
		}
	}

	@Override
	public String execute()  {
		if(!isAjax()){
			queryPagination();
		}
		return SUCCESS;
	}
	
	public String index(){
		return SUCCESS;
	}

	public String list() {
		return execute();
	}
	
	/**
	 * 获得列表数据
	 */
	public void datagrid() {
		queryPagination();
		writeJson(pagination,WriterCode.PAGINATION);
	}
	
	/**
	 * 查看/预览对象
	 * @return
	 */
	public String view(){
		if(!isAjax()){
			if (Validators.isEmpty(id)) {
				return INPUT;
			}
			doGetViewEntity();
			afterGetViewEntity();
		}
		return SUCCESS;
	}
	protected void doGetViewEntity(){
		entity =  defaultService.get(id, entityClass,voClass);
	}
	protected void afterGetViewEntity(){};
	
	/**
	 * 新增表单
	 * @return
	 */
	public String form() {
		if(!isAjax()){
			if (Validators.isEmpty(id)) {
				return SUCCESS;
			}
			doGetEntity();
			afterGetEntity();
		}
		return SUCCESS;
	}
	protected void doGetEntity(){
		entity =  defaultService.get(id, entityClass,voClass);
	}
	protected void afterGetEntity(){};
	
	public String edit() {
		if(!isAjax()){
			if (Validators.isEmpty(id)) {
				return SUCCESS;
			}
			doGetEntity();
			afterGetEntity();
		}
		return SUCCESS;
	}

	/**
	 * 新增
	 * @throws MelonRuntimeException
	 */
	public final void add() throws MelonException{
		if(!beforeAdd()){
			writeBaseJsonMessage("", resolveErrors(), MessageLevel.ERROR, "html");
			return;
		}
		try{
			doAdd();
			afterAdd();
			writeBaseJsonMessage(getText(SYSTEM_MESSAGE_TITLE,""), addSuccMsg(), MessageLevel.INFO, "html");
		}catch(MelonException e){
			writeBaseJsonMessage(getText(SYSTEM_MESSAGE_TITLE,""), addFailMsg(e), MessageLevel.ERROR, "html");
		}catch(Exception e){
			e.printStackTrace();
			writeError(e.getMessage());
		}
	}
	
	protected boolean beforeAdd(){
		return !hasErrors();
	}
	
	protected void doAdd() throws Exception{
		defaultService.save(entity,entityClass);
	}
	protected void afterAdd(){}
	protected String addSuccMsg(){
		return getText(ACTION_SUCCESS);
	}
	protected String addFailMsg(Exception e){
		return getText(e.getMessage());
	}
	/**
	 * 修改
	 * @throws MelonException
	 */
	public final void update() throws MelonException{
		if(!beforeUpdate()){
			writeBaseJsonMessage("", resolveErrors(), MessageLevel.ERROR, "html");
			return;
		}
		try{
			doUpdate();
			afterUpdate();
			writeBaseJsonMessage("", updateSuccMsg(), MessageLevel.INFO, "html");
		}catch(MelonException e){
			writeBaseJsonMessage("", updateFailMsg(e), MessageLevel.ERROR, "html");
		}catch(Exception e){
			e.printStackTrace();
			writeError(e.getMessage());
		}
	}
	
	protected boolean beforeUpdate(){return !hasErrors();}
	protected void doUpdate() throws Exception{
		defaultService.update(entity,entityClass);
	}
	protected void afterUpdate(){}
	protected String updateSuccMsg(){
		return getText(ACTION_SUCCESS);
	}
	protected String updateFailMsg(Exception e){
		return getText(e.getMessage());
	}
	
	/**
	 * 加载数据到页面
	 * @throws MelonRuntimeException
	 */
	@SuppressWarnings("deprecation")
	public void load() throws MelonRuntimeException {
		if (Validators.isEmpty(id)) {
			return;
		}
		doLoad();
		afterLoad();
		writeJson(entity,WriterCode.FORM);
	}
	
	protected void doLoad(){
		entity = defaultService.get(id, entityClass,voClass);
	}
	protected void afterLoad(){}
	/**
	 * 删除
	 * @throws MelonRuntimeException
	 */
	public final void delete() throws MelonRuntimeException {
//		if (Validators.isEmpty(deletes)) {
//			writeBaseJsonMessage(getText(SYSTEM_MESSAGE_TITLE),getText(ACTION_DELETE_ERROR), MessageLevel.ERROR);
//			return;
//		}
		if(!beforeDelete()){
			return;
		}
		try {
			doDelete();
			afterDelete();
			writeBaseJsonMessage(getText(SYSTEM_MESSAGE_TITLE), deleteSuccMsg(), MessageLevel.INFO);
		}  catch (MelonException e) {
			writeBaseJsonMessage(getText(SYSTEM_MESSAGE_TITLE), deleteFailMsg(e),
					MessageLevel.ERROR);
		}catch(Exception e){
			writeError(e.getMessage());
		}
	}
	
	protected boolean beforeDelete(){ return true;}
	protected void doDelete() throws Exception{
		if(!StringUtils.hasText(deletes)){
			return;
		}
		for (String str : deletes.split(";")) {
			P t = entityClass.newInstance();
			((PrimaryKey) t).setId(str);
			defaultService.delete(t);
		}
	}
	protected void afterDelete(){}
	protected String deleteSuccMsg(){
		return getText(ACTION_DELETE_SUCCESS);
	}
	protected String deleteFailMsg(Exception e){
		return getText(e.getMessage());
	}
	
	
	/**
	 * overwrite if needed
	 */
	protected void doQueryPage() {
		pagination = defaultService.queryPageByQueryBuilder(pagination,getListVoClass());
	}
	
	protected void afterQueryPage(){}
	
	/**
	 * 当有特殊query需要注入时使用
	 */
	protected void extraQuery(){
		
	}
	
	private void queryPagination(){
		if (pagination == null) {
			pagination = new Pagination(entityClass);
		}
		pagination.setSearcher(getSearcher());
		//querySearcher();
		//queryParameters(pagination);
		extraQuery();
		doQueryPage();
		afterQueryPage();
	}
	
	protected void querySearcher(){
		Searcher searcher = getSearcher();
		if(searcher==null){
			return;
		}
		QueryBuilder qb = pagination.getQueryBuilder();
		for(SearcherColumn column : searcher.getColumns()){
			//String key = column.getKey();
			Object value = column.getValue();
			SymbolExpression operator  = SymbolExpression.getValueWithException(column.getType());
			String queryname = column.getKey();
//			if(key.indexOf("_")>0){
//				try{
//					//operator = SymbolExpression.getValueWithException(key.substring(0,key.indexOf("_")));
//				}catch(NoSuchElementException e){
//					operator = SymbolExpression.EQUAL;//默认就是equal
//				}
//				queryname = key.substring(key.indexOf("_")+1).replaceAll("#", "\\.");//将#转为.
//			}else{
//				queryname = key.replaceAll("#", "\\.");
//			}
			SymbolExpression.append(qb, operator, queryname, value);
		}
		for(SearcherColumn order : searcher.getOrders()){
			String key = order.getKey();
			String value = order.getValue().toString();
			OrderExpression operator ;
			try{
				operator = OrderExpression.getValueWithException(value);
			}catch(NoSuchElementException e){
				operator = OrderExpression.DESC;//默认就是equal
			}
			OrderExpression.append(qb, operator, key);
		}
	}
	
	public String getSearcherName(){
		StringBuilder sb = new StringBuilder(SEARCH_PREFIX);
		sb.append(getClass().getName());
		return sb.toString();
	}
	
	public Searcher getSearcher(){
		return ActionContext.getSearcher(getSearcherName());
	}
	
	@Override
	public boolean clearOnReload() {
		return true;
	}

	@Override
	public boolean singleOrder() {
		return true;
	}

	@SuppressWarnings("unchecked")
	protected void generateClass(){
		entityClass = (Class<P>) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		voClass = (Class<V>) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[1];
	}
	
	protected boolean isAjax() {
		return ajax;
	}

	public void setAjax(boolean ajax) {
		this.ajax = ajax;
	}

	/************************ setter & getter *********************************/
	public Pagination getPagination() {
		return pagination;
	}

	public void setPagination(Pagination pagination) {
		this.pagination = pagination;
	}

	public void setDeletes(String deletes) {
		this.deletes = deletes;
	}

	public void setPage(int page) {
		if (pagination == null) {
			pagination = new Pagination(entityClass);
		}
		pagination.setPage(page);
	}

	public void setRows(int rows) {
		if (pagination == null) {
			pagination = new Pagination(entityClass);
		}
		pagination.setRp(rows);
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
	

	//不能用抽象函数或者函数去迫使子类重写，struts真操蛋！
	//public abstract V getEntity();
	
	//public abstract void setEntity(V entity);
	
	public boolean isCheckbox() {
		return checkbox;
	}

	public void setCheckbox(boolean checkbox) {
		this.checkbox = checkbox;
	}

	/**
	 * 列表对象重写,默认form的vo和list的vo一致
	 * @return
	 */
	protected Class<?> getListVoClass(){
		return voClass;
	}

	public void setDefaultService(DefaultService defaultService) {
		this.defaultService = defaultService;
	}
	
	public String getDatagridTitle(String fieldName){
		return getDatagridTitle(entityClass.getName(), fieldName);
	}
	
	public String getDatagridTitle(String classname,String fieldName){
		String reval =  getProperty(classname, fieldName+AbstractPojo.POJO_FIELD_TITLE_POSTFIX);
		if(reval==null){
			reval = "";
		}
		return reval;
	}
	
	public String getPojoDes(String fieldName,String postFix){
		String reval =  getProperty(entityClass.getName(), fieldName+"."+postFix);
		if(reval==null){
			reval = "";
		}
		return reval;
	}
	
	protected String resolveErrors(){
		StringBuilder sb = new StringBuilder();
		for(Map.Entry<String, List<String>> entry : getFieldErrors().entrySet()){
			for(String str : entry.getValue()){
				sb.append(str).append("<br>");
			}
		}
		for(String str : getActionErrors()){
			sb.append(str).append("<br>");
		}
		return sb.toString();
	}
	
}
